#include "Element.h"

namespace xml{

    /********************************************
     *              Public
     ********************************************/

        /********************************************
         *              Constructors
         ********************************************/

            Element::Element(){
                m_Type  =   ELEMENT_NODE;
            }

            Element::Element(string tagNam){
                m_Type  =   ELEMENT_NODE;
                tagName =   tagNam;
            }

            Element::Element(ifstream &f){
                m_Type  =   ELEMENT_NODE;
                try{
                    if(!LoadElement(f)){
                        throw(" Error, could not load Element");
                    }
                }catch(string str){
                    printf("Error : %s \n", str.c_str());
                }
            }

        /********************************************
         *              Methods
         ********************************************/

            string Element::Value(){
                string val;
                for(int i=0;i<Childs.size();i++){
                    val= Childs.at(i)->Value();
                }
                return val;
            }

            void Element::Print(){
                printf("tagName :  %s \n", tagName.c_str());

                for(int i=0; i< attributes.size(); i++){
                    attributes.at(i)->Print();
                }
                for(int i=0;i< Childs.size();i++){
                    Childs[i]->Print();
                }
            }

            void Element::Save(ofstream &f){
                SaveTagName(f);
                SaveAttributes(f);
                SaveContent(f);
            }

            Element * Element::GetElementByTagName(string tagname){
                for(int i=0; i< Childs.size();i++){
                    if(Childs.at(i)->Type()==ELEMENT_NODE){
                        Element * el = (Element*) Childs.at(i);
                        if(el->tagName==tagname){
                            return (el);
                        }
                    }
                }
                return NULL;
            }

    /********************************************
     *              Private
     ********************************************/

        /********************************************
         *              Methods
         ********************************************/

            bool Element::LoadElement(ifstream &f){
                try{
                    if(!LoadTag(f)){
                        throw("TagName not loaded");
                    }else if(!LoadAttributes(f)){
                        throw("Attributes not loaded");
                    }else if(!LoadContent(f)){
                        throw("Error while Loading Element content");
                    }
                    return true;
                }catch(string strError){
                    printf(" Error while Loading Element : %s \n", strError.c_str());
                    return false;
                }
            }

            bool Element::LoadTag(ifstream & f){
                try{
                    stringstream str;
                    char c;
                    c=f.get();
                    while (c !='>' && !f.eof() && !XML::IsEmptyChar(c)){
                        if(c=='<'){
                            throw(" character \"<\"  detected inside a tag at line ");
                        }else if(c=='"'){
                            throw(" Character \"\"\" detected inside a tag name");
                        }
                        str << c;
                        c=f.get();
                    }
                    str >> tagName;
                    f.unget();
                    return true;
                }catch( string error){
                    printf(" Error while loading tag : %s \n", error.c_str());
                    return false;
                }
            }

            bool Element::LoadAttributes(ifstream &f){
                try{
                    char c = f.get();
                    while(c!='>'){
                        if(c!=' ' && c!='    ' && c!='\n'){
                            f.unget(); // Attribute will extract first char
                            Attribute * attr = new Attribute(f);
                            if(attr->Error){
                                throw(" Error");
                            }
                            attributes.push_back(attr);
                        }
                    c=f.get();
                    }
                }catch(string strError){
                    printf("Error Attributes \n");
                    return false;
                }
            }

            bool Element::LoadContent(ifstream &f){
                char c;
                bool end = false;
                while (!end && !f.eof()){
                    c=f.get();
                    if(c=='<'){
                        if(f.peek()!='/'){
                            Childs.push_back(new Element(f));
                        }else{
                            f.get();
                            stringstream textnode;
                            while (c !='>' && !f.eof()){
                                textnode<< c;
                                c=f.get();
                            }
                            end=true;
                        }
                    }else if( !XML::IsEmptyChar(c)){
                        stringstream textnode;

                        while (c !='<') {
                            textnode<< c;
                            c=f.get();
                        }
                        f.unget();
                        Childs.push_back(new TextNode( textnode.str()));
                    }
                }
                return true;
            }



            void Element::SaveTagName(ofstream &f){
                f<<GetTabValue()<<"<"<<tagName;
            }

            void Element::SaveAttributes(ofstream &f){
                for(int i=0;i< attributes.size(); i++){
                    attributes.at(i)->Save(f);
                }
                f<<">\n";
            }

            void Element::SaveContent(ofstream &f){
                for(int i=0; i< Childs.size();i++){
                    Childs.at(i)->Save(f);
                }
                 f<<"\n"<<GetTabValue()<<"</"<<tagName<<">\n";;
            }




}
